
/**
** \file       exec_cmdline.c
**
** \brief      This file contains the functions who will execute the main
**             command line.
**             ./42sh -c "string" will be executed by exec_str
**             ./42sh file will be executed by exec_file
**             ./42sh will be executed by exec_readline
**
** \authors    Ben M'rad Hanna, Boillot Ulysse, De Oliveira Guillaume,
**             Laterem Hamza et Nguyen Viet Dung coded this file as a part
**             of the 42sh project.
**
** \version    0.8
**
** \data       26 November 2010
**
*/

#include "exec_cmdline.h"

s_data          *g_data = NULL;

static char     **init_keyword(void)
{
  g_data->tab_keyword = malloc(SIZE2 * sizeof (char *));

  g_data->tab_keyword[0] = "if";
  g_data->tab_keyword[1] = "else";
  g_data->tab_keyword[2] = "then";
  g_data->tab_keyword[3] = "fi";
  g_data->tab_keyword[4] = "case";
  g_data->tab_keyword[5] = "esac";
  g_data->tab_keyword[6] = "for";
  g_data->tab_keyword[7] = "in";
  g_data->tab_keyword[8] = "while";
  g_data->tab_keyword[9] = "do";
  g_data->tab_keyword[10] = "until";
  g_data->tab_keyword[11] = "done";
  g_data->tab_keyword[12] = "elif";
  g_data->tab_keyword[13] = "function";

  return (g_data->tab_keyword);
}

static s_token  *init_tabtoken(void)
{
  g_data->tab_token = malloc(SIZE * sizeof (s_token));

  g_data->tab_token[0] = (s_token) {TOKEN_COMMENT, "#"};
  g_data->tab_token[1] = (s_token) {TOKEN_NEWLINE, "\n"};
  g_data->tab_token[2] = (s_token) {TOKEN_EOF, "EOF"};
  g_data->tab_token[3] = (s_token) {TOKEN_OPEN_P, "("};
  g_data->tab_token[4] = (s_token) {TOKEN_EXCL, "!"};
  g_data->tab_token[5] = (s_token) {TOKEN_CLOSE_P, ")"};
  g_data->tab_token[6] = (s_token) {TOKEN_IONUMBER, "IONUMBER"};
  g_data->tab_token[7] = (s_token) {TOKEN_OR, "|"};
  g_data->tab_token[8] = (s_token) {TOKEN_DAND, "&&"};
  g_data->tab_token[9] = (s_token) {TOKEN_DOR, "||"};
  g_data->tab_token[10] = (s_token) {TOKEN_DSEMI, ";;"};
  g_data->tab_token[11] = (s_token) {TOKEN_SEMI, ";"};
  g_data->tab_token[12] = (s_token) {TOKEN_DLESS, "<<"};
  g_data->tab_token[13] = (s_token) {TOKEN_DGREAT, ">>"};
  g_data->tab_token[14] = (s_token) {TOKEN_AND, "&"};
  g_data->tab_token[15] = (s_token) {TOKEN_DLESSDASH, "<<-"};
  g_data->tab_token[16] = (s_token) {TOKEN_LESSGREAT, "<>"};
  g_data->tab_token[17] = (s_token) {TOKEN_LESSAND, "<&"};
  g_data->tab_token[18] = (s_token) {TOKEN_GREATAND, ">&"};
  g_data->tab_token[19] = (s_token) {TOKEN_LESS, "<"};
  g_data->tab_token[20] = (s_token) {TOKEN_GREAT, ">"};
  g_data->tab_token[21] = (s_token) {TOKEN_GREATPIPE, ">|"};
  g_data->tab_token[22] = (s_token) {TOKEN_WORD, "WORD"};

  return (g_data->tab_token);
}

s_data          *init_data(char         **envp)
{
  g_data = malloc(sizeof (s_data));

  g_data->lexer = malloc(sizeof (s_lexer));
  g_data->lexer->token = malloc(sizeof (s_token));
  g_data->lexer->next = NULL;
  g_data->lexer->head = g_data->lexer;

  g_data->tab_token = init_tabtoken();
  g_data->tab_keyword = init_keyword();

  g_data->ast = malloc(sizeof (s_ast));
  g_data->ast->list = NULL;

  g_data->envp = envp;

  return (g_data);
}

static int      no_file(void)
{
  write(STDERR_FILENO, "Error: file does not exist\n", 27);

  return (1);
}

static int      ret(int                 i,
                    char                *buf)
{
  free(buf);

  return (i);
}

int             exec_file(char          *file,
                          s_cmd         *cmd,
                          char          **envp)
{
  char          *buf = NULL;
  int           fd = 0;
  int           i = 0;

  fd = open(file, O_RDONLY);

  if (fd == -1)
    return (no_file());

  buf = malloc(sizeof (char));
  read(fd, buf, 1);

  while (buf[i] != EOF)
  {
    while (buf[i] != '\n')
    {
      buf = realloc(buf, i + 2);
      read(fd, buf + ++i, 1);
    }
    if (exec_str(buf, cmd, envp) != 0)
      return (ret(1, buf));

    buf = realloc(buf, sizeof (char));
    read(fd, buf, 1);
    i = 0;
  }

  return (ret(0, buf));
}

static void     free_data(s_data        *data)
{
  free(data->tab_token);
  free(data->tab_keyword);
  free_lexer(data->lexer);
  free_ast(data->ast);
  free(data);
}

int             exec_str(char           *str,
                         s_cmd          *cmd,
                         char           **envp)
{
  int           res = 0;
  int           j = 0;
  char          *tmp = NULL;
  s_opt         *tmp_opt = NULL;

  g_data = init_data(envp);

  tmp = malloc(sizeof (char) * strlen(str) + 1);
  tmp = strcpy(tmp, str);
  tmp = realloc(tmp, (j = strlen(tmp)) + 2);
  tmp[j] = '\n';
  tmp[j + 1] = '\0';

  g_data->lexer = rec_lexer(tmp, g_data->lexer);

  g_data->ast = rule_input(g_data->ast);

  tmp_opt = cmd->opt;

  while (tmp_opt != NULL && strcmp(tmp_opt->name, "--ast-print") != 0)
    tmp_opt = tmp_opt->next;

  if (tmp_opt != NULL)
    print_ast(g_data->ast);

  res = exec_input(g_data->ast);

  if (g_data->ast == NULL)
    write(STDERR_FILENO, "42sh: syntax error\n", 19);

  free_data(g_data);

  free(tmp);
  return (res);
}

int             exec_cmdline(s_cmd      *cmd_res,
                             char       **argv,
                             char       **envp)
{
  s_opt         *tmp_opt = NULL;
  int           loop = 1;
  int           fd = 0;

  tmp_opt = cmd_res->opt;

  while (tmp_opt != NULL && strcmp(tmp_opt->name, "-c") != 0)
    tmp_opt = tmp_opt->next;

  if (tmp_opt != NULL)
    return (exec_str(tmp_opt->aux, cmd_res, envp));

  if (cmd_res->file != NULL)
    return (exec_file(cmd_res->file->name, cmd_res, envp));

  fd = open("history", O_RDWR | O_CREAT | O_APPEND, S_IRWXU);

  while (loop)
  {
    if ((loop = exec_readline(argv, cmd_res, envp)) < 0)
    {
      close(fd);
      if (loop == -1)
        return (0);

      return (1);
    }

    loop = 1;
  }

  close(fd);
  return (0);
}
